package cate.game.role.pay;

import cate.common.game.GameCollection;
import cate.common.table.d.GDFunc;
import cate.common.table.d.GDObj;
import cate.common.table.d.GDOperation;
import cate.common.table.pay.PayItemRow;
import cate.game.event.pay.AfterPayEvent;
import cate.game.pay.PayCallback;
import cate.game.pay.PayDeliverParam;
import cate.game.pay.msg.RolePayInitResp;
import cate.game.pay.sample.PayShopSampleCallback;
import cate.game.res.MixResAdder;
import cate.game.role.Role;
import cate.game.role.RolePart;
import cate.game.role.pay.limittimeggift.LimitTimeGift;
import cate.game.role.pay.trademall.TradeMallPO;
import cate.game.role.pay.trademall.forevercontract.paycallback.ForeverContractCallback;
import cate.game.role.res.guild.po.my.GuildPayCallBack;
import cate.game.util.api.StatApi;
import com.fasterxml.jackson.annotation.JsonIgnore;
import cp.solution.business.pay.PayRecordEntity;
import cp.solution.business.pay.dto.PayDeliverResult;
import cp.solution.define.PayOrderType;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcException;
import easy.java.practice.errorcode.EcResult;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.*;

@Document(collection = GameCollection.NAME_ROLE_PAY)
public class RolePay extends RolePart {

    @NoteField("笔记")
    public String note;

    @NoteField(value = "历史累计充值数额(分)")
    public long paySum;
    @NoteField(value = "历史累计充值次数")
    public long payTimes;
    @NoteField(value = "上次充值时间")
    public long lastPayTime;
    @NoteField(value = "交易坊")
    public TradeMallPO tradeMall;
    @NoteField("限时礼包")
    public LimitTimeGift gift;
    @NoteField(value = "客服返利日志", detail = "Map<返利编码, 日志内容> map有key意味着已发放奖励")
    public Map<String, String> kfRebateLogs;

    @Transient
    @JsonIgnore
    @NoteField(value = "演示商店代码", detail = "仅供演示，后期会删除")
    public transient PayShopSample shopSample = new PayShopSample();

    @Transient
    private transient Set<String> ing = new HashSet<>();

    public RolePay() {
    }

    public RolePay(Role role) {
        super(role);
    }

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (tradeMall == null) {
            tradeMall = new TradeMallPO();
        }
        tradeMall.initialize(role);
        if (gift == null) {
            gift = new LimitTimeGift();
        }
        gift.initialize(role);
    }

    /**
     * 受理支付服的兑现支付请求
     */
    public PayDeliverResult deliver(PayRecordEntity record, PayDeliverParam param) {
        PayDeliverResult r = new PayDeliverResult();
        r.setGsVer("第3版支付处理逻辑");
        // 支付请求的各种条件判断
        if (ing.contains(record.getPlatformOrderId())) {
            throw new EcException("订单" + record.getPlatformOrderId() + "游戏服正在处理中，本次重复请求被忽略");
        }
        ing.add(record.getPlatformOrderId());
        //
        try {
            PayItemRow pir = role.getGame().table.pay.item.get(record.itemTid);
            PayCallback cb = null;
            switch (pir.funcId) {
                case GDFunc.PAY_SHOP_SAMPLE:
                    cb = new PayShopSampleCallback();
                    break;
                case GDFunc.GuildFunc.ENVELOP:
                    cb = new GuildPayCallBack();
                    break;
                case GDFunc.FOREVER_CONTRACT:
                    cb = new ForeverContractCallback();
                    break;
                default:
                    break;
            }
            if (cb == null) {
                cb = role.getGame().pay.getPayHandler(pir.funcId);
            }
            if (cb != null) {
                boolean needRecheck = record.orderType == PayOrderType.NORMAL
                        || record.orderType == PayOrderType.OUTSIDE
                        || record.orderType == PayOrderType.TB
                        || record.orderType == PayOrderType.DEVELOP;
                EcResult allowRes = needRecheck ? PayCheck.allow(pir, role) : new EcResult();
                if (allowRes.ok()) {
                    cb.onSuccess(role.getGame(), role, record, r);
                } else {
                    r.setBusinessComment(allowRes.message);
                    logger.error(
                            "玩家{}支付兑现失败 充值项ID为：{} 原因为：{}",
                            role.getBase().name,
                            pir.id,
                            allowRes);
                    new MixResAdder()
                            .setRes(GDObj.getMixResStr(GDObj.Type.NUM, GDObj.Num.M1, record.payCents / 10))
                            .setOperation(GDOperation.PAY_RULE_BREAK)
                            .setOperationSub(pir.id)
                            .setDialogReward(true)
                            .exe(role);
                }
            }
            afterPay(record, pir.vipPoints, param);
        } finally {
            ing.remove(record.getPlatformOrderId());
        }
        StatApi.updateRoleRecord(role);
        new RolePayInitResp(role.getPay()).sendNow(role);
        return r;
    }

    /**
     * 支付后续操作
     */
    public void afterPay(PayRecordEntity record, long vipPoints, PayDeliverParam param) {
        // 累计充值数量
        paySum += record.payCents;
        payTimes++;
        lastPayTime = System.currentTimeMillis();
        // 触发事件
        final long vp = param.noVipPoints ? 0 : vipPoints;
        publishEvent(role, new AfterPayEvent(role, vp, record));
        if (payTimes == 1) {
            StatApi.uploadFirstPayLog(role, record);
            firstPayLampOnline();
        }
    }

    private void firstPayLampOnline() {
    }

    @Override
    public void onDaySpan(boolean silence) {
        tradeMall.onDaySpanSafe(silence);
        gift.onDaySpanSafe(silence);
    }

    @Override
    public void onWeekSpan(boolean silence) {
        tradeMall.onWeekSpanSafe(silence);
    }

    @Override
    public void onMonthSpan(boolean silence) {
        tradeMall.onMonthSpanSafe(silence);
    }

    @Override
    public void onEnter() {
        tradeMall.onEnter();
    }

    public void tick() {
        gift.tick();
        tradeMall.privilegeMall.tick();
    }
}
